Ejercicio de Simulación
Vamos a hacer un ejercicio de simulación para ver como se identifica
la componente estacional.
library(urca)
library(forecast)
library(tseries)
‘tseries’ version: 0.10-51
‘tseries’ is a package for time series analysis and
computational finance.
See ‘library(help="tseries")’ for details.
library(lmtest)
Loading required package: zoo
Attaching package: ‘zoo’
The following objects are masked from ‘package:base’:
as.Date, as.Date.numeric
Attaching package: ‘lmtest’
The following object is masked _by_ ‘.GlobalEnv’:
unemployment
library(uroot)
library(fUnitRoots)
Loading required package: timeDate
Loading required package: timeSeries
Attaching package: ‘timeSeries’
The following object is masked from ‘package:zoo’:
time<-
Loading required package: fBasics
Attaching package: ‘fUnitRoots’
The following objects are masked from ‘package:urca’:
punitroot, qunitroot, unitrootTable
library(sarima)
Loading required package: stats4
Attaching package: ‘sarima’
The following object is masked from ‘package:stats’:
spectrum
require("PolynomF")
Loading required package: PolynomF
###Simulación de un proceso con raíz unitaria estacional
#x11()
x <- ts(sarima::sim_sarima(n=144, model = list(iorder=0, siorder=1, nseasons=12, sigma2 = 1),n.start=24),frequency = 12)
plot(x)

acf(x,lag.max = 36)

monthplot(x)

nsdiffs(x)####Decreta cuantas diferencias estacional a través de la aplicación de
[1] 1
###Algunas pruebas de raíces unitarias estacionales.
###diferencia estacional
Dx=diff(x,lag=12,differences = 1)###lag:periodo s.
plot(Dx)

acf(Dx,lag.max = 36)

monthplot(Dx)

nsdiffs(Dx)
[1] 0
####Simulación de un SAR
#x11()
x1 <- ts(sim_sarima(n=144, model = list(ar=c(rep(0,11),0.8)),n.start=24),frequency=12)
plot(x1)

acf(x1,lag.max = 36)

monthplot(x1)

nsdiffs(x1)
[1] 0
ndiffs(x1)
[1] 0
p <- polynom(c(1,c(rep(0,11),-0.8)))
solve(p)
[1] -1.0187693+0.0000000i -0.8822801-0.5093846i -0.8822801+0.5093846i
[4] -0.5093846-0.8822801i -0.5093846+0.8822801i 0.0000000-1.0187693i
[7] 0.0000000+1.0187693i 0.5093846-0.8822801i 0.5093846+0.8822801i
[10] 0.8822801-0.5093846i 0.8822801+0.5093846i 1.0187693+0.0000000i
abs(solve(p))
[1] 1.018769 1.018769 1.018769 1.018769 1.018769 1.018769 1.018769
[8] 1.018769 1.018769 1.018769 1.018769 1.018769
###Note lo cerca que están la raíces de la no estacionariedad del proceso, por eso
####aunque si bien el proceso es estacionario, notamos hay una cercanía a
####e tener una componente estacional.
####El anterior modelo puede escribirse como:
x2 <- ts(sim_sarima(n=144, model=list(sar=0.8, iorder=0, siorder=0, nseasons=12),n.start=24),frequency = 12)
plot(x2)

acf(x2, lag.max=48)

monthplot(x2)

nsdiffs(x2)
[1] 1
x3=ts(sim_sarima(n=144, model=list(sar=0.7, sma=0.5, iorder=0, siorder=1, nseasons=12),n.start=24),frequency = 12)
plot(x3)

acf(x3, lag.max=48)

monthplot(x3)

nsdiffs(x3)
[1] 1
###diferencia estacional
Dx3=diff(x3,lag=12,differences = 1)###lag:periodo s.
plot(Dx3)

acf(Dx3,lag.max = 36)

monthplot(Dx3)

nsdiffs(Dx3)
[1] 0
#########3
x3=ts(sim_sarima(n=144, model=list(ma=0.6, sma=0.5, iorder=0, siorder=1, nseasons=12),n.start=24),frequency = 12)
plot(x3)

acf(x3, lag.max=48)

monthplot(x3)

nsdiffs(x3)
[1] 1
Dx3=diff(x3,lag=12,differences = 1)###lag:periodo s.
plot(Dx3)

acf(Dx3,lag.max = 36)

monthplot(Dx3)

nsdiffs(Dx3)
[1] 0
Ejemplo Pasajeros
Vamos a ver como se hace el modelamiento completo de la serie de
pasajeros.
Iniciaremos con la transformación Box-Cox y las pruebas de raíces
Unitarias


[1] 1
Call:
ar(x = lAirpassengers)
Coefficients:
1 2 3 4 5 6 7 8
1.0013 -0.0959 0.0329 -0.0252 0.0231 0.0005 -0.0157 -0.0762
9 10 11 12 13
0.1071 -0.0236 0.0675 0.4536 -0.4854
Order selected 13 sigma^2 estimated as 0.01336
Augmented Dickey-Fuller Test
data: lAirpassengers
Dickey-Fuller = -2.147, Lag order = 13, p-value = 0.5152
alternative hypothesis: stationary
Warning: p-value greater than printed p-value
Title:
Augmented Dickey-Fuller Test
Test Results:
PARAMETER:
Lag Order: 12
STATISTIC:
Dickey-Fuller: 3.7872
P VALUE:
0.99
Description:
Thu Oct 27 08:19:54 2022 by user:
###############################################
# Augmented Dickey-Fuller Test Unit Root Test #
###############################################
Test regression none
Call:
lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)
Residuals:
Min 1Q Median 3Q Max
-0.103864 -0.023652 -0.001455 0.022160 0.126649
Coefficients:
Estimate Std. Error t value Pr(>|t|)
z.lag.1 0.005439 0.001436 3.787 0.000241 ***
z.diff.lag1 -0.198813 0.072080 -2.758 0.006737 **
z.diff.lag2 -0.273730 0.073309 -3.734 0.000292 ***
z.diff.lag3 -0.233607 0.072258 -3.233 0.001589 **
z.diff.lag4 -0.293133 0.073926 -3.965 0.000126 ***
z.diff.lag5 -0.206562 0.072058 -2.867 0.004915 **
z.diff.lag6 -0.266919 0.071493 -3.734 0.000292 ***
z.diff.lag7 -0.234526 0.071847 -3.264 0.001436 **
z.diff.lag8 -0.327393 0.073197 -4.473 1.79e-05 ***
z.diff.lag9 -0.198455 0.073623 -2.696 0.008054 **
z.diff.lag10 -0.279931 0.072710 -3.850 0.000192 ***
z.diff.lag11 -0.176122 0.073011 -2.412 0.017394 *
z.diff.lag12 0.627402 0.072683 8.632 3.34e-14 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.04308 on 118 degrees of freedom
Multiple R-squared: 0.8564, Adjusted R-squared: 0.8406
F-statistic: 54.14 on 13 and 118 DF, p-value: < 2.2e-16
Value of test-statistic is: 3.7872
Critical values for test statistics:
1pct 5pct 10pct
tau1 -2.58 -1.95 -1.62
Title:
Augmented Dickey-Fuller Test
Test Results:
PARAMETER:
Lag Order: 12
STATISTIC:
Dickey-Fuller: -1.5325
P VALUE:
0.7711
Description:
Thu Oct 27 08:19:54 2022 by user:
Call:
ar(x = dlAirpassengers)
Coefficients:
1 2 3 4 5 6 7 8
-0.0993 -0.1226 -0.2824 -0.2875 -0.1184 -0.2406 -0.1829 -0.2971
9 10 11 12 13 14 15
-0.1040 -0.2627 -0.1259 0.5734 0.0179 -0.1667 0.1200
Order selected 15 sigma^2 estimated as 0.002988
Augmented Dickey-Fuller Test
data: dlAirpassengers
Dickey-Fuller = -3.3376, Lag order = 15, p-value = 0.0678
alternative hypothesis: stationary
Title:
Augmented Dickey-Fuller Test
Test Results:
PARAMETER:
Lag Order: 12
STATISTIC:
Dickey-Fuller: -1.2228
P VALUE:
0.2243
Description:
Thu Oct 27 08:20:04 2022 by user:
Identificación de la componente ARMA estacional y la componente ARMA
ordinaria
####################################
library(uroot)
require(forecast)
######Diferencia Estacional(continuación AirPassengers)#######
monthplot(dlAirpassengers)
nsdiffs(dlAirpassengers)
[1] 1
nsdiffs(AirPassengers)
[1] 1
DdlAirpassengers=diff(dlAirpassengers,lag=12)###lag=s
#x11()
par(mfrow=c(2,1))

plot(dlAirpassengers)
plot(DdlAirpassengers)

monthplot(DdlAirpassengers)
nsdiffs(DdlAirpassengers)
[1] 0
##Autocorrelogramas
#x11()
acf(DdlAirpassengers)

acf(DdlAirpassengers,lag.max = 48, ci.type='ma')# q=0,1, Q=0,1
pacf(DdlAirpassengers,lag.max = 48) # p=0,1,2,...,9, P=0,1

#SARIMA(p=0,d=1,q=1)x(P=0,D=1,Q=1)s=12
Ajuste del Modelo y Análisis de Residuales
##Ajuste del modelo
###Arima Estacional o SARIMA(p=0,d=1,q=3)x(P=0,D=1,Q=1)s=12 con transformación logaritmica
#Modelo MA(1) estacional
modelo = Arima(AirPassengers, c(0, 1, 1),seasonal = list(order = c(0, 1, 1), period = 12),lambda = 0)
coeftest(modelo)
z test of coefficients:
Estimate Std. Error z value Pr(>|z|)
ma1 -0.401828 0.089644 -4.4825 7.378e-06 ***
sma1 -0.556945 0.073100 -7.6190 2.557e-14 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
modeloalter= Arima(AirPassengers, c(1, 1, 0),seasonal = list(order = c(1, 1, 0), period = 12),lambda = 0)
## Análisis de residuales
#x11()
residuales <- modelo$residuals
plot(residuales)

acf(residuales,lag.max = 24)

pacf(residuales,lag.max = 24)
#Test de autocorrelaci?n
Box.test(residuales, lag = (length(residuales)/4), type = "Ljung-Box", fitdf = 2)
Box-Ljung test
data: residuales
X-squared = 37.874, df = 34, p-value = 0.2969
######Análisis de Outliers
#Test de normalidad
jarque.bera.test(residuales)
Jarque Bera Test
data: residuales
X-squared = 5.2265, df = 2, p-value = 0.0733
###Estad?ticas CUSUM
res=residuales
cum=cumsum(res)/sd(res)
N=length(res)
cumq=cumsum(res^2)/sum(res^2)
Af=0.948 ###Cuantil del 95% para la estad?stica cusum
co=0.14422####Valor del cuantil aproximado para cusumsq para n/2
LS=Af*sqrt(N)+2*Af*c(1:length(res))/sqrt(N)
LI=-LS
LQS=co+(1:length(res))/N
LQI=-co+(1:length(res))/N
par(mfrow=c(2,1))

plot(cum,type="l",ylim=c(min(LI),max(LS)),xlab="t",ylab="",main="CUSUM")
lines(LS,type="S",col="red")
lines(LI,type="S",col="red")
#CUSUM Square
plot(cumq,type="l",xlab="t",ylab="",main="CUSUMSQ")
lines(LQS,type="S",col="red")
lines(LQI,type="S",col="red")

Pronóstico
#x11()
Pronosticos=forecast(modelo,h=12,level=0.95)
plot(Pronosticos)
predic<-predict(modelo,n.ahead=12)
plot(predic$pred)
#####Comparación de pronósticos####
library(fpp)
train <- window(AirPassengers,start=c(1949,01),end=c(1959,12))
test <- window(AirPassengers,start=c(1960,01),end=c(1960,12))
fitmodelo <- Arima(AirPassengers, c(0, 1, 1),seasonal = list(order = c(0, 1, 1), period = 12),lambda = 0)
refit <- Arima(AirPassengers, model=fitmodelo)
fc <- window(fitted(refit), start=c(1960,1))
h <- 1
train <- window(AirPassengers,start=c(1949,01),end=c(1959,12))
test <- window(AirPassengers,start=c(1960,01),end=c(1960,12))
n <- length(test) - h + 1
fitmodelo <- Arima(AirPassengers, c(0, 1, 1),seasonal = list(order = c(0, 1, 1), period = 12),lambda = 0)
fc <- ts(numeric(n), start=c(1960,01), freq=12)
for(i in 1:n)
{
x <- window(AirPassengers, end=c(1959, 12+(i-1)))
refit <- Arima(x, model=fitmodelo)
fc[i] <- forecast(refit, h=h)$mean[h]
}
dife=(test-fc)^2
ecm=(1/(length(test)))*sum(dife)
ecm
library(tidyverse)
library(tidyquant)
library(TSstudio)
library(SLBDD)
library(timetk)
library(fable)
library(feasts)
AirPassengers_tsb=as_tsibble(AirPassengers)
Ajuste_tsibble_Pass<- AirPassengers_tsb %>%
model(
sarima011011_Pass = ARIMA(log(value) ~ pdq(0,1,1) + PDQ(0,1,1)),
auto_pass = ARIMA(log(value), stepwise = TRUE, approx = FALSE),
dummy_Pass=ARIMA(log(value) ~ pdq(0,1,1)+ season()),
fourier_Pass=ARIMA(log(value) ~ pdq(0,1,1)+ fourier(K = 2))
)
glance(Ajuste_tsibble_Pass)
#Ajuste_tsibble_Pass %>% select(sarima011011_Pass)%>%
# gg_tsresiduals()
#augment(Ajuste_tsibble_Pass) %>%
# filter(.model=='sarima011011_Pass') %>%
# features(.innov, ljung_box, lag = 10, dof = 3)
Ajuste_tsibble_Pass %>%
fabletools::forecast(h=12) %>%
autoplot(AirPassengers_tsb)
Ajuste_tsibble_Pass %>%
fabletools::forecast(h=12) %>%
filter(.model=='sarima011011_Pass') %>%
autoplot(AirPassengers_tsb)
Ajuste_tsibble_Pass %>%
fabletools::forecast(h=12) %>%
filter(.model=='dummy_Pass') %>%
autoplot(AirPassengers_tsb)
Ajuste_tsibble_Pass %>%
fabletools::forecast(h=12) %>%
filter(.model=='fourier_Pass') %>%
autoplot(AirPassengers_tsb)
Vale la pena decir que si los residuales son no correlacionados pero
ellos no tiene distribución normal, se puede usar los intervalos
bootatrap ver sección 5.5 libro fpp3. Esto se hace añadiendo
bootstrap=TRUE en la función forecast().
Intervenciones
Accidentes laborales desde enero de 1979 hasta diciembre de 1998.
Aquí vamos a tener en cuenta tres variables de intervención: * \(D_t:\) número de días laborales. * \(I_{1t}^{(h)}:\) variable de impulso que
toma el valor 1 si la semana santa cae en ese mes, y cero en otro caso.
* \(I_{2t}^{(h)}:\) Variable que toma
el valor de 1 cuando febrero tiene un día más por ser un año
bisiesto.
La razón por la cual es razonable incluir estas variables es porque
el número de accidentes laborales puede estar siendo afectado por estos
sucesos. Sin embargo, hay mas formas de incluir tales efectos, por
ejemplo la función calendar.effects del paquete tsoutliers extrae estos
efectos pero desde otra respectiva. Por ejemplo, para los días laborales
se calcula una variable asociada llamada día laboral(\(td_t\)), la cual es como sigue: Sea \(wd_t\) el número de días laborales por
ejemplo en un mes t. \(nwd_t\) es el
número de días no laborales en el mes \(t\). La variable \(td_t\) es como sigue: \[wd_t=\# \text{días
laborales}-festivos\]
\[nwd_t=\# \text{días no
laborales}+festivos\] y así
\[td_t=wd_t-(5/2)nwd_t.\] Los días
laborales son los días de lunes a viernes, y los días no laborales son
los sábados y domingos. El número de días festivos en el tiempo \(t\) se pasan como un objeto para la función
a través del argumento holidays. El efecto de semana santa se define
como la porción de días antes de la semana santa(de un total de 6 por
defecto) que caen en marzo y abril.Los restantes meses se les asigna el
valor de cero.
El año bisiesto se asocia con un valor de 0.75 al mes de febrero si
el año es bisiesto, en caso contrario es -0.25. Los demás meses se
definen con cero.
Accidentes_tsibble%>%autoplot()
Plot variable not specified, automatically selected `.vars = Accidentes`

Acá construimos las variables para los efectos de calendario.
Adicionalmente, vamos a incluir una variable cambio de nivel para
febrero de 1988, ya que se introdujo una nueva definición de accidente
laboral en la ley Española. Esta variable de paso se define como sigue:
\[S_t^{(110)}=\begin{cases}
0 & \text{si } t<110,\\
1 & \text{si } t\geq 110.
\end{cases}
\] El valor de 110 es porque corresponde a la observación número
110 en el tiempo. Esta variable se puede crear usando la función
filter.
Una función cambio transitorio, tambien puede incluirse \[C(t)=\frac{\omega B}{1-\delta
B}S_{t}^{(h)}\]
como sigue “tc_0_4 <- filter(tc, filter = 0.4, method
=”recursive”)”

Vamos ajustar un modelo basado en el logaritmo del número de
accidentes. Un modelo incial propuesto sin las regresoras es: \[SARIMA((2,1,0)\times(1,1,1))\]
forecast::forecast(modelo_accidentes_xreg,h=1,xreg=regresoras_futuras)
Warning: xreg contains different column names from the xreg used in training. Please check that the regressors are in the same order.
ajuste_final<-aus_cafe%>%model(
`FourierK=1`=ARIMA(log(Turnover)~fourier(K=1)+pdq(1,1,0)+PDQ(0,0,0),),
`FourierK=2`=ARIMA(log(Turnover)~fourier(K=2)+pdq(1,1,0)+PDQ(0,0,0)),
`FourierK=3`=ARIMA(log(Turnover)~fourier(K=3)+pdq(1,1,0)+PDQ(0,0,0)),
`Dummy`=ARIMA(log(Turnover)~season()+pdq(1,1,0)+PDQ(0,0,0)) )
LS0tCnRpdGxlOiAiU0FSSU1BIgpvdXRwdXQ6IAogIGdpdGh1Yl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMjIEVqZXJjaWNpbyBkZSBTaW11bGFjacOzbgoKVmFtb3MgYSBoYWNlciB1biBlamVyY2ljaW8gZGUgc2ltdWxhY2nDs24gcGFyYSB2ZXIgY29tbyBzZSBpZGVudGlmaWNhIGxhIGNvbXBvbmVudGUgZXN0YWNpb25hbC4KCmBgYHtyIFNpbXVsYWNpb259CmxpYnJhcnkodXJjYSkKbGlicmFyeShmb3JlY2FzdCkKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGxtdGVzdCkKbGlicmFyeSh1cm9vdCkKbGlicmFyeShmVW5pdFJvb3RzKQpsaWJyYXJ5KHNhcmltYSkKcmVxdWlyZSgiUG9seW5vbUYiKQoKIyMjU2ltdWxhY2nDs24gZGUgdW4gcHJvY2VzbyBjb24gcmHDrXogdW5pdGFyaWEgZXN0YWNpb25hbAojeDExKCkKeCA8LSB0cyhzYXJpbWE6OnNpbV9zYXJpbWEobj0xNDQsIG1vZGVsID0gbGlzdChpb3JkZXI9MCwgc2lvcmRlcj0xLCBuc2Vhc29ucz0xMiwgc2lnbWEyID0gMSksbi5zdGFydD0yNCksZnJlcXVlbmN5ID0gMTIpCnBsb3QoeCkKYWNmKHgsbGFnLm1heCA9IDM2KQptb250aHBsb3QoeCkKbnNkaWZmcyh4KSMjIyNEZWNyZXRhIGN1YW50YXMgZGlmZXJlbmNpYXMgZXN0YWNpb25hbCBhIHRyYXbDqXMgZGUgbGEgYXBsaWNhY2nDs24gZGUgCiMjI0FsZ3VuYXMgcHJ1ZWJhcyBkZSByYcOtY2VzIHVuaXRhcmlhcyBlc3RhY2lvbmFsZXMuCgoKIyMjZGlmZXJlbmNpYSBlc3RhY2lvbmFsCkR4PWRpZmYoeCxsYWc9MTIsZGlmZmVyZW5jZXMgPSAxKSMjI2xhZzpwZXJpb2RvIHMuCnBsb3QoRHgpCmFjZihEeCxsYWcubWF4ID0gMzYpCm1vbnRocGxvdChEeCkKbnNkaWZmcyhEeCkKIyMjI1NpbXVsYWNpw7NuIGRlIHVuIFNBUgojeDExKCkKeDEgPC0gdHMoc2ltX3NhcmltYShuPTE0NCwgbW9kZWwgPSBsaXN0KGFyPWMocmVwKDAsMTEpLDAuOCkpLG4uc3RhcnQ9MjQpLGZyZXF1ZW5jeT0xMikKcGxvdCh4MSkKYWNmKHgxLGxhZy5tYXggPSAzNikKbW9udGhwbG90KHgxKQpuc2RpZmZzKHgxKQpuZGlmZnMoeDEpCnAgPC0gcG9seW5vbShjKDEsYyhyZXAoMCwxMSksLTAuOCkpKQpzb2x2ZShwKQphYnMoc29sdmUocCkpCiMjI05vdGUgbG8gY2VyY2EgcXVlIGVzdMOhbiBsYSByYcOtY2VzIGRlIGxhIG5vIGVzdGFjaW9uYXJpZWRhZCBkZWwgcHJvY2VzbywgcG9yIGVzbwojIyMjYXVucXVlIHNpIGJpZW4gZWwgcHJvY2VzbyBlcyBlc3RhY2lvbmFyaW8sIG5vdGFtb3MgaGF5IHVuYSBjZXJjYW7DrWEgYSAKIyMjI2UgdGVuZXIgdW5hIGNvbXBvbmVudGUgZXN0YWNpb25hbC4KIyMjI0VsIGFudGVyaW9yIG1vZGVsbyBwdWVkZSBlc2NyaWJpcnNlIGNvbW86CngyIDwtIHRzKHNpbV9zYXJpbWEobj0xNDQsIG1vZGVsPWxpc3Qoc2FyPTAuOCwgaW9yZGVyPTAsIHNpb3JkZXI9MCwgbnNlYXNvbnM9MTIpLG4uc3RhcnQ9MjQpLGZyZXF1ZW5jeSA9IDEyKQpwbG90KHgyKQphY2YoeDIsIGxhZy5tYXg9NDgpCm1vbnRocGxvdCh4MikKbnNkaWZmcyh4MikKCngzPXRzKHNpbV9zYXJpbWEobj0xNDQsIG1vZGVsPWxpc3Qoc2FyPTAuNywgc21hPTAuNSwgaW9yZGVyPTAsIHNpb3JkZXI9MSwgbnNlYXNvbnM9MTIpLG4uc3RhcnQ9MjQpLGZyZXF1ZW5jeSA9IDEyKQpwbG90KHgzKQphY2YoeDMsIGxhZy5tYXg9NDgpCm1vbnRocGxvdCh4MykKbnNkaWZmcyh4MykKCiMjI2RpZmVyZW5jaWEgZXN0YWNpb25hbApEeDM9ZGlmZih4MyxsYWc9MTIsZGlmZmVyZW5jZXMgPSAxKSMjI2xhZzpwZXJpb2RvIHMuCnBsb3QoRHgzKQphY2YoRHgzLGxhZy5tYXggPSAzNikKbW9udGhwbG90KER4MykKbnNkaWZmcyhEeDMpCgoKCiMjIyMjIyMjIzMKeDM9dHMoc2ltX3NhcmltYShuPTE0NCwgbW9kZWw9bGlzdChtYT0wLjYsIHNtYT0wLjUsIGlvcmRlcj0wLCBzaW9yZGVyPTEsIG5zZWFzb25zPTEyKSxuLnN0YXJ0PTI0KSxmcmVxdWVuY3kgPSAxMikKcGxvdCh4MykKYWNmKHgzLCBsYWcubWF4PTQ4KQptb250aHBsb3QoeDMpCm5zZGlmZnMoeDMpCgpEeDM9ZGlmZih4MyxsYWc9MTIsZGlmZmVyZW5jZXMgPSAxKSMjI2xhZzpwZXJpb2RvIHMuCnBsb3QoRHgzKQphY2YoRHgzLGxhZy5tYXggPSAzNikKbW9udGhwbG90KER4MykKbnNkaWZmcyhEeDMpCgoKCgpgYGAKCiMjIEVqZW1wbG8gUGFzYWplcm9zCgpWYW1vcyBhIHZlciBjb21vIHNlIGhhY2UgZWwgbW9kZWxhbWllbnRvIGNvbXBsZXRvIGRlIGxhIHNlcmllIGRlIHBhc2FqZXJvcy4KCkluaWNpYXJlbW9zIGNvbiBsYSB0cmFuc2Zvcm1hY2nDs24gQm94LUNveCB5IGxhcyBwcnVlYmFzIGRlIHJhw61jZXMgVW5pdGFyaWFzCgpgYGB7ciBwYXNzZW5nZXJzLCBlY2hvPUZBTFNFfQojIyMjIyNBanVzdGUgU2VyaWUgZGF0b3MgQWlyUGFzc2VuZ2VycyBwb3IgbWVkaW8gZGVsCiNtb2RlbG8gQVJJTUEgZXN0YWNpb25hbCwgYXPDrSBjb21vIHN1IGNvcnJlc3BvbmRpZW50ZQojYW7DoWxpc2lzIGRlIHJlc2lkdWFsZXMgeSBwcm9uw7NzdGljb3MKCmRhdGEoQWlyUGFzc2VuZ2VycykKcGxvdChBaXJQYXNzZW5nZXJzKQojIyMjIyMjIyMjRGVzcHXDqXMgZGUgaGFiZXIgYXBsaWNhZG8gbGEgZGlmZXJlbmNpYSBvcmRpbmFyaWEgeSBlc3RhY2lvbmFsCiMjIyMjI1Byb2NlZGVtb3MgYSB0cmF0YXIgZGUgaWRlbnRpZmljYXIgbGEgZXN0cnVjdHVyYSBkZSBhdXRvY29ycmVsYWNpw7NuCiMjI2EgY29ydG8gcGxhem8oQVJNQSkgeSBlc3RhY2lvbmFsIFNBUk1BLgojIyNQYXJhIGVzbywgZXMgbmVjZXNhcmlvIGhhYmVyIGNvbnZlcnRpZG8gbGEgc2VyaWUgYSBlc3RhY2lvbmFyaWEjIyMKbEFpcnBhc3NlbmdlcnM9bG9nKEFpclBhc3NlbmdlcnMpCnBsb3QobEFpcnBhc3NlbmdlcnMpCm1vbnRocGxvdChsQWlycGFzc2VuZ2VycykKCmZvcmVjYXN0OjpuZGlmZnMobEFpcnBhc3NlbmdlcnMpCiMjIyMjUHJ1ZWJhIGRlIERpY2tleSBGdWxsZXIjIyMjIyMKYXIobEFpcnBhc3NlbmdlcnMpCnRzZXJpZXM6OmFkZi50ZXN0KGxBaXJwYXNzZW5nZXJzLGs9MTMpCmZVbml0Um9vdHM6OmFkZlRlc3QobEFpcnBhc3NlbmdlcnMsbGFncyA9IDEyLHR5cGU9J25jJykgICAjIyNIYXkgbGEgcHJlc2VuY2lhIGRlIFJhw616IFVuaXRhcmlhCnN1bW1hcnkodXJjYTo6dXIuZGYobEFpcnBhc3NlbmdlcnMsIGxhZ3MgPSAxMikpCmFkZlRlc3QobEFpcnBhc3NlbmdlcnMsbGFncz0xMix0eXBlPSdjdCcpICAjIyMjUHVlZGUgdGFtYmnDqW4gaW5kaWNhcgojIyMjTGEgcHJlc2VuY2lhIGRlIHVuYSB0ZW5kZW5jaWEgZGV0ZXJtaW7DrXN0aWNhCgojIyMjRGlmZXJlbmNpYSBPcmRpbmFyaWEjIyMjIyMjIyMjIyMKCmRsQWlycGFzc2VuZ2Vycz1kaWZmKGxBaXJwYXNzZW5nZXJzLGxhZz0xKQp4MTEoKQpwYXIobWZyb3c9YygyLDEpKQpwbG90KGxBaXJwYXNzZW5nZXJzKQpwbG90KGRsQWlycGFzc2VuZ2VycykKYXIoZGxBaXJwYXNzZW5nZXJzKQoKdHNlcmllczo6YWRmLnRlc3QoZGxBaXJwYXNzZW5nZXJzLGsgPSAxNSkgICMjI05vIHNlIGRlYmUgZGlmZXJlbmNpYXIgbcOhcyMjIwoKZlVuaXRSb290czo6YWRmVGVzdChkbEFpcnBhc3NlbmdlcnMsbGFncyA9IDEyLHR5cGU9J25jJykgCgpgYGAKCiMjIElkZW50aWZpY2FjacOzbiBkZSBsYSBjb21wb25lbnRlIEFSTUEgZXN0YWNpb25hbCB5IGxhIGNvbXBvbmVudGUgQVJNQSBvcmRpbmFyaWEKCmBgYHtyIENvbXBvbmVudGUgRXN0YWNpb25hbCB5IE9yZGluYXJpYX0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmxpYnJhcnkodXJvb3QpCnJlcXVpcmUoZm9yZWNhc3QpCiMjIyMjI0RpZmVyZW5jaWEgRXN0YWNpb25hbChjb250aW51YWNpw7NuIEFpclBhc3NlbmdlcnMpIyMjIyMjIwptb250aHBsb3QoZGxBaXJwYXNzZW5nZXJzKQpuc2RpZmZzKGRsQWlycGFzc2VuZ2VycykKbnNkaWZmcyhBaXJQYXNzZW5nZXJzKQoKRGRsQWlycGFzc2VuZ2Vycz1kaWZmKGRsQWlycGFzc2VuZ2VycyxsYWc9MTIpIyMjbGFnPXMKI3gxMSgpCnBhcihtZnJvdz1jKDIsMSkpCnBsb3QoZGxBaXJwYXNzZW5nZXJzKQpwbG90KERkbEFpcnBhc3NlbmdlcnMpCm1vbnRocGxvdChEZGxBaXJwYXNzZW5nZXJzKQpuc2RpZmZzKERkbEFpcnBhc3NlbmdlcnMpCgoKIyNBdXRvY29ycmVsb2dyYW1hcwojeDExKCkKYWNmKERkbEFpcnBhc3NlbmdlcnMpCmFjZihEZGxBaXJwYXNzZW5nZXJzLGxhZy5tYXggPSA0OCwgY2kudHlwZT0nbWEnKSMgcT0wLDEsIFE9MCwxCnBhY2YoRGRsQWlycGFzc2VuZ2VycyxsYWcubWF4ID0gNDgpICMgcD0wLDEsMiwuLi4sOSwgUD0wLDEKI1NBUklNQShwPTAsZD0xLHE9MSl4KFA9MCxEPTEsUT0xKXM9MTIKYGBgCgoKIyMgQWp1c3RlIGRlbCBNb2RlbG8geSBBbsOhbGlzaXMgZGUgUmVzaWR1YWxlcwpgYGB7ciBBanVzdGVzIHkgUmVzaWR1YWxlc30KIyNBanVzdGUgZGVsIG1vZGVsbwojIyNBcmltYSBFc3RhY2lvbmFsIG8gU0FSSU1BKHA9MCxkPTEscT0zKXgoUD0wLEQ9MSxRPTEpcz0xMiBjb24gdHJhbnNmb3JtYWNpw7NuIGxvZ2FyaXRtaWNhCgojTW9kZWxvIE1BKDEpIGVzdGFjaW9uYWwKbW9kZWxvID0gQXJpbWEoQWlyUGFzc2VuZ2VycywgYygwLCAxLCAxKSxzZWFzb25hbCA9IGxpc3Qob3JkZXIgPSBjKDAsIDEsIDEpLCBwZXJpb2QgPSAxMiksbGFtYmRhID0gMCkKY29lZnRlc3QobW9kZWxvKQptb2RlbG9hbHRlcj0gQXJpbWEoQWlyUGFzc2VuZ2VycywgYygxLCAxLCAwKSxzZWFzb25hbCA9IGxpc3Qob3JkZXIgPSBjKDEsIDEsIDApLCBwZXJpb2QgPSAxMiksbGFtYmRhID0gMCkKCiMjIEFuw6FsaXNpcyBkZSByZXNpZHVhbGVzCiN4MTEoKQpyZXNpZHVhbGVzIDwtIG1vZGVsbyRyZXNpZHVhbHMKcGxvdChyZXNpZHVhbGVzKQphY2YocmVzaWR1YWxlcyxsYWcubWF4ID0gMjQpCnBhY2YocmVzaWR1YWxlcyxsYWcubWF4ID0gMjQpCiNUZXN0IGRlIGF1dG9jb3JyZWxhY2k/bgpCb3gudGVzdChyZXNpZHVhbGVzLCBsYWcgPSAobGVuZ3RoKHJlc2lkdWFsZXMpLzQpLCB0eXBlID0gIkxqdW5nLUJveCIsIGZpdGRmID0gMikKIyMjIyMjQW7DoWxpc2lzIGRlIE91dGxpZXJzCiNUZXN0IGRlIG5vcm1hbGlkYWQKamFycXVlLmJlcmEudGVzdChyZXNpZHVhbGVzKQoKCgojIyNFc3RhZD90aWNhcyBDVVNVTQpyZXM9cmVzaWR1YWxlcwpjdW09Y3Vtc3VtKHJlcykvc2QocmVzKQpOPWxlbmd0aChyZXMpCmN1bXE9Y3Vtc3VtKHJlc14yKS9zdW0ocmVzXjIpCkFmPTAuOTQ4ICMjI0N1YW50aWwgZGVsIDk1JSBwYXJhIGxhIGVzdGFkP3N0aWNhIGN1c3VtCmNvPTAuMTQ0MjIjIyMjVmFsb3IgZGVsIGN1YW50aWwgYXByb3hpbWFkbyBwYXJhIGN1c3Vtc3EgcGFyYSBuLzIKTFM9QWYqc3FydChOKSsyKkFmKmMoMTpsZW5ndGgocmVzKSkvc3FydChOKQpMST0tTFMKTFFTPWNvKygxOmxlbmd0aChyZXMpKS9OCkxRST0tY28rKDE6bGVuZ3RoKHJlcykpL04KcGFyKG1mcm93PWMoMiwxKSkKcGxvdChjdW0sdHlwZT0ibCIseWxpbT1jKG1pbihMSSksbWF4KExTKSkseGxhYj0idCIseWxhYj0iIixtYWluPSJDVVNVTSIpCmxpbmVzKExTLHR5cGU9IlMiLGNvbD0icmVkIikKbGluZXMoTEksdHlwZT0iUyIsY29sPSJyZWQiKQojQ1VTVU0gU3F1YXJlCnBsb3QoY3VtcSx0eXBlPSJsIix4bGFiPSJ0Iix5bGFiPSIiLG1haW49IkNVU1VNU1EiKSAgICAgICAgICAgICAgICAgICAgICAKbGluZXMoTFFTLHR5cGU9IlMiLGNvbD0icmVkIikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKbGluZXMoTFFJLHR5cGU9IlMiLGNvbD0icmVkIikKCmBgYAoKIyMgUHJvbsOzc3RpY28KCmBgYHtyIFByb25vc3RpY299CiN4MTEoKQpQcm9ub3N0aWNvcz1mb3JlY2FzdChtb2RlbG8saD0xMixsZXZlbD0wLjk1KQpwbG90KFByb25vc3RpY29zKQpwcmVkaWM8LXByZWRpY3QobW9kZWxvLG4uYWhlYWQ9MTIpCnBsb3QocHJlZGljJHByZWQpCgoKIyMjIyNDb21wYXJhY2nDs24gZGUgcHJvbsOzc3RpY29zIyMjIwpsaWJyYXJ5KGZwcCkKdHJhaW4gPC0gd2luZG93KEFpclBhc3NlbmdlcnMsc3RhcnQ9YygxOTQ5LDAxKSxlbmQ9YygxOTU5LDEyKSkKdGVzdCA8LSB3aW5kb3coQWlyUGFzc2VuZ2VycyxzdGFydD1jKDE5NjAsMDEpLGVuZD1jKDE5NjAsMTIpKQpmaXRtb2RlbG8gPC0gQXJpbWEoQWlyUGFzc2VuZ2VycywgYygwLCAxLCAxKSxzZWFzb25hbCA9IGxpc3Qob3JkZXIgPSBjKDAsIDEsIDEpLCBwZXJpb2QgPSAxMiksbGFtYmRhID0gMCkKcmVmaXQgPC0gQXJpbWEoQWlyUGFzc2VuZ2VycywgbW9kZWw9Zml0bW9kZWxvKQpmYyA8LSB3aW5kb3coZml0dGVkKHJlZml0KSwgc3RhcnQ9YygxOTYwLDEpKQoKCmggPC0gMQp0cmFpbiA8LSB3aW5kb3coQWlyUGFzc2VuZ2VycyxzdGFydD1jKDE5NDksMDEpLGVuZD1jKDE5NTksMTIpKQp0ZXN0IDwtIHdpbmRvdyhBaXJQYXNzZW5nZXJzLHN0YXJ0PWMoMTk2MCwwMSksZW5kPWMoMTk2MCwxMikpCm4gPC0gbGVuZ3RoKHRlc3QpIC0gaCArIDEKZml0bW9kZWxvIDwtIEFyaW1hKEFpclBhc3NlbmdlcnMsIGMoMCwgMSwgMSksc2Vhc29uYWwgPSBsaXN0KG9yZGVyID0gYygwLCAxLCAxKSwgcGVyaW9kID0gMTIpLGxhbWJkYSA9IDApCmZjIDwtIHRzKG51bWVyaWMobiksIHN0YXJ0PWMoMTk2MCwwMSksIGZyZXE9MTIpCmZvcihpIGluIDE6bikKeyAgCiAgeCA8LSB3aW5kb3coQWlyUGFzc2VuZ2VycywgZW5kPWMoMTk1OSwgMTIrKGktMSkpKQogIHJlZml0IDwtIEFyaW1hKHgsIG1vZGVsPWZpdG1vZGVsbykKICBmY1tpXSA8LSBmb3JlY2FzdChyZWZpdCwgaD1oKSRtZWFuW2hdCn0KZGlmZT0odGVzdC1mYyleMgplY209KDEvKGxlbmd0aCh0ZXN0KSkpKnN1bShkaWZlKQplY20KYGBgCgpgYGB7ciBPdHJvcyBNb2RlbGFtaWVudG99CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRpZHlxdWFudCkKbGlicmFyeShUU3N0dWRpbykKbGlicmFyeShTTEJERCkKbGlicmFyeSh0aW1ldGspCmxpYnJhcnkoZmFibGUpCmxpYnJhcnkoZmVhc3RzKQpBaXJQYXNzZW5nZXJzX3RzYj1hc190c2liYmxlKEFpclBhc3NlbmdlcnMpCkFqdXN0ZV90c2liYmxlX1Bhc3M8LSBBaXJQYXNzZW5nZXJzX3RzYiAlPiUKICBtb2RlbCgKICAgIHNhcmltYTAxMTAxMV9QYXNzID0gQVJJTUEobG9nKHZhbHVlKSB+IHBkcSgwLDEsMSkgKyBQRFEoMCwxLDEpKSwKICAgIGF1dG9fcGFzcyA9IEFSSU1BKGxvZyh2YWx1ZSksIHN0ZXB3aXNlID0gVFJVRSwgYXBwcm94ID0gRkFMU0UpLCAKICBkdW1teV9QYXNzPUFSSU1BKGxvZyh2YWx1ZSkgfiBwZHEoMCwxLDEpKyBzZWFzb24oKSksCiBmb3VyaWVyX1Bhc3M9QVJJTUEobG9nKHZhbHVlKSB+IHBkcSgwLDEsMSkrIGZvdXJpZXIoSyA9IDIpKQogKQoKZ2xhbmNlKEFqdXN0ZV90c2liYmxlX1Bhc3MpCgojQWp1c3RlX3RzaWJibGVfUGFzcyAlPiUgc2VsZWN0KHNhcmltYTAxMTAxMV9QYXNzKSU+JQogIyBnZ190c3Jlc2lkdWFscygpCgojYXVnbWVudChBanVzdGVfdHNpYmJsZV9QYXNzKSAlPiUKIyAgZmlsdGVyKC5tb2RlbD09J3NhcmltYTAxMTAxMV9QYXNzJykgJT4lCiMgIGZlYXR1cmVzKC5pbm5vdiwgbGp1bmdfYm94LCBsYWcgPSAxMCwgZG9mID0gMykKCkFqdXN0ZV90c2liYmxlX1Bhc3MgJT4lCiAgZmFibGV0b29sczo6Zm9yZWNhc3QoaD0xMikgJT4lCiAgYXV0b3Bsb3QoQWlyUGFzc2VuZ2Vyc190c2IpCgpBanVzdGVfdHNpYmJsZV9QYXNzICU+JQogIGZhYmxldG9vbHM6OmZvcmVjYXN0KGg9MTIpICU+JQogIGZpbHRlcigubW9kZWw9PSdzYXJpbWEwMTEwMTFfUGFzcycpICU+JQogIGF1dG9wbG90KEFpclBhc3NlbmdlcnNfdHNiKQoKQWp1c3RlX3RzaWJibGVfUGFzcyAlPiUKICBmYWJsZXRvb2xzOjpmb3JlY2FzdChoPTEyKSAlPiUKICBmaWx0ZXIoLm1vZGVsPT0nZHVtbXlfUGFzcycpICU+JQogIGF1dG9wbG90KEFpclBhc3NlbmdlcnNfdHNiKQoKQWp1c3RlX3RzaWJibGVfUGFzcyAlPiUKICBmYWJsZXRvb2xzOjpmb3JlY2FzdChoPTEyKSAlPiUKICBmaWx0ZXIoLm1vZGVsPT0nZm91cmllcl9QYXNzJykgJT4lCiAgYXV0b3Bsb3QoQWlyUGFzc2VuZ2Vyc190c2IpCgpgYGAKVmFsZSBsYSBwZW5hIGRlY2lyIHF1ZSBzaSBsb3MgcmVzaWR1YWxlcyBzb24gbm8gY29ycmVsYWNpb25hZG9zIHBlcm8gZWxsb3Mgbm8gdGllbmUgZGlzdHJpYnVjacOzbiBub3JtYWwsIHNlIHB1ZWRlIHVzYXIgbG9zIGludGVydmFsb3MgYm9vdGF0cmFwIHZlciBzZWNjacOzbiA1LjUgbGlicm8gZnBwMy4gRXN0byBzZSBoYWNlIGHDsWFkaWVuZG8gYm9vdHN0cmFwPVRSVUUgZW4gbGEgZnVuY2nDs24gIGZvcmVjYXN0KCkuCgoKIyBJbnRlcnZlbmNpb25lcwoKQWNjaWRlbnRlcyBsYWJvcmFsZXMgZGVzZGUgZW5lcm8gZGUgMTk3OSBoYXN0YSBkaWNpZW1icmUgZGUgMTk5OC4gQXF1w60gdmFtb3MgYSB0ZW5lciBlbiBjdWVudGEgdHJlcyB2YXJpYWJsZXMgZGUgaW50ZXJ2ZW5jacOzbjoKKiAkRF90OiQgbsO6bWVybyBkZSBkw61hcyBsYWJvcmFsZXMuCiogJElfezF0fV57KGgpfTokIHZhcmlhYmxlIGRlIGltcHVsc28gcXVlIHRvbWEgZWwgdmFsb3IgMSBzaSBsYSBzZW1hbmEgc2FudGEgY2FlIGVuIGVzZSBtZXMsIHkgY2VybyBlbiBvdHJvIGNhc28uCiogJElfezJ0fV57KGgpfTokIFZhcmlhYmxlICBxdWUgdG9tYSBlbCB2YWxvciBkZSAxIGN1YW5kbyBmZWJyZXJvIHRpZW5lIHVuIGTDrWEgbcOhcyBwb3Igc2VyIHVuIGHDsW8gYmlzaWVzdG8uCgpMYSByYXrDs24gcG9yIGxhIGN1YWwgZXMgcmF6b25hYmxlIGluY2x1aXIgZXN0YXMgdmFyaWFibGVzIGVzIHBvcnF1ZSBlbCBuw7ptZXJvIGRlIGFjY2lkZW50ZXMgbGFib3JhbGVzIHB1ZWRlIGVzdGFyIHNpZW5kbyBhZmVjdGFkbyBwb3IgZXN0b3Mgc3VjZXNvcy4KU2luIGVtYmFyZ28sIGhheSBtYXMgZm9ybWFzIGRlIGluY2x1aXIgdGFsZXMgZWZlY3RvcywgcG9yIGVqZW1wbG8gbGEgZnVuY2nDs24gY2FsZW5kYXIuZWZmZWN0cyBkZWwgcGFxdWV0ZSB0c291dGxpZXJzIGV4dHJhZSBlc3RvcyBlZmVjdG9zIHBlcm8gZGVzZGUgb3RyYSByZXNwZWN0aXZhLiBQb3IgZWplbXBsbywgcGFyYSBsb3MgZMOtYXMgbGFib3JhbGVzIHNlIGNhbGN1bGEgdW5hIHZhcmlhYmxlIGFzb2NpYWRhIGxsYW1hZGEgZMOtYSBsYWJvcmFsKCR0ZF90JCksIGxhIGN1YWwgZXMgY29tbyBzaWd1ZTogU2VhICR3ZF90JCBlbCBuw7ptZXJvIGRlIGTDrWFzIGxhYm9yYWxlcyBwb3IgZWplbXBsbyBlbiB1biBtZXMgdC4gJG53ZF90JCBlcyBlbCBuw7ptZXJvIGRlIGTDrWFzIG5vIGxhYm9yYWxlcyBlbiBlbCBtZXMgJHQkLiBMYSB2YXJpYWJsZSAkdGRfdCQgZXMgY29tbyBzaWd1ZToKJCR3ZF90PVwjIFx0ZXh0e2TDrWFzIGxhYm9yYWxlc30tZmVzdGl2b3MkJAoKJCRud2RfdD1cIyBcdGV4dHtkw61hcyBubyBsYWJvcmFsZXN9K2Zlc3Rpdm9zJCQKeSBhc8OtCgokJHRkX3Q9d2RfdC0oNS8yKW53ZF90LiQkCkxvcyBkw61hcyBsYWJvcmFsZXMgc29uIGxvcyBkw61hcyBkZSBsdW5lcyBhIHZpZXJuZXMsIHkgbG9zIGTDrWFzIG5vIGxhYm9yYWxlcyBzb24gbG9zIHPDoWJhZG9zIHkgZG9taW5nb3MuIEVsIG7Dum1lcm8gZGUgZMOtYXMgZmVzdGl2b3MgZW4gZWwgdGllbXBvICR0JCBzZSBwYXNhbiBjb21vIHVuIG9iamV0byBwYXJhIGxhIGZ1bmNpw7NuIGEgdHJhdsOpcyBkZWwgYXJndW1lbnRvIGhvbGlkYXlzLiBFbCBlZmVjdG8gZGUgc2VtYW5hIHNhbnRhIHNlIGRlZmluZSBjb21vIGxhIHBvcmNpw7NuIGRlIGTDrWFzIGFudGVzIGRlIGxhIHNlbWFuYSBzYW50YShkZSB1biB0b3RhbCBkZSA2IHBvciBkZWZlY3RvKSBxdWUgY2FlbiBlbiBtYXJ6byB5IGFicmlsLkxvcyByZXN0YW50ZXMgbWVzZXMgc2UgbGVzIGFzaWduYSBlbCB2YWxvciBkZSBjZXJvLgoKRWwgYcOxbyBiaXNpZXN0byBzZSBhc29jaWEgY29uIHVuIHZhbG9yIGRlIDAuNzUgYWwgbWVzIGRlIGZlYnJlcm8gc2kgZWwgYcOxbyBlcyBiaXNpZXN0bywgZW4gY2FzbyBjb250cmFyaW8gZXMgLTAuMjUuIExvcyBkZW3DoXMgbWVzZXMgc2UgZGVmaW5lbiBjb24gY2Vyby4KCgpgYGB7ciBJbnRlcnZlbmNpw7NuIDF9CmxpYnJhcnkodHNvdXRsaWVycykKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkodHNpYmJsZSkKbGlicmFyeSh0aW1lRGF0ZSkKbGlicmFyeShsYXJlcykKbGlicmFyeShiaXpkYXlzKQoKQWNjaWRlbnRlczwtcmVhZF9yZHMoZmlsZSA9ICJBY2NpZGVudGVzLnJkcyIpCkFjY2lkZW50ZXNfZm9ybWF0b19mZWNoYT1BY2NpZGVudGVzCkFjY2lkZW50ZXNfZm9ybWF0b19mZWNoYSRGZWNoYXM8LXllYXJtb250aChBY2NpZGVudGVzX2Zvcm1hdG9fZmVjaGEkRmVjaGFzKQoKCkFjY2lkZW50ZXNfdHNpYmJsZT1hc190c2liYmxlKEFjY2lkZW50ZXNfZm9ybWF0b19mZWNoYSkKQWNjaWRlbnRlc190c2liYmxlCgpBY2NpZGVudGVzX3RzaWJibGUlPiVhdXRvcGxvdCgpCgoKCmBgYApBY8OhIGNvbnN0cnVpbW9zIGxhcyB2YXJpYWJsZXMgcGFyYSBsb3MgZWZlY3RvcyBkZSBjYWxlbmRhcmlvLiBBZGljaW9uYWxtZW50ZSwgdmFtb3MgYSBpbmNsdWlyIHVuYSB2YXJpYWJsZSBjYW1iaW8gZGUgbml2ZWwgcGFyYSBmZWJyZXJvIGRlIDE5ODgsIHlhIHF1ZSBzZSBpbnRyb2R1am8gdW5hIG51ZXZhIGRlZmluaWNpw7NuIGRlIGFjY2lkZW50ZSBsYWJvcmFsIGVuIGxhIGxleSBFc3Bhw7FvbGEuIEVzdGEgdmFyaWFibGUgZGUgcGFzbyBzZSBkZWZpbmUgY29tbyBzaWd1ZToKJCRTX3ReeygxMTApfT1cYmVnaW57Y2FzZXN9CjAgJiBcdGV4dHtzaSB9IHQ8MTEwLFxcCjEgJiBcdGV4dHtzaSB9IHRcZ2VxIDExMC4KXGVuZHtjYXNlc30KJCQKRWwgdmFsb3IgZGUgMTEwIGVzIHBvcnF1ZSBjb3JyZXNwb25kZSBhIGxhIG9ic2VydmFjacOzbiBuw7ptZXJvIDExMCBlbiBlbCB0aWVtcG8uIEVzdGEgdmFyaWFibGUgc2UgcHVlZGUgY3JlYXIgdXNhbmRvIGxhIGZ1bmNpw7NuIGZpbHRlci4KClVuYSBmdW5jacOzbiBjYW1iaW8gdHJhbnNpdG9yaW8sIHRhbWJpZW4gcHVlZGUgaW5jbHVpcnNlCiQkQyh0KT1cZnJhY3tcb21lZ2EgQn17MS1cZGVsdGEgQn1TX3t0fV57KGgpfSQkCgpjb21vIHNpZ3VlICJ0Y18wXzQgPC0gZmlsdGVyKHRjLCBmaWx0ZXIgPSAwLjQsIG1ldGhvZCA9ICJyZWN1cnNpdmUiKSIKYGBge3IgZWZlY3RvcyBkZSBjYWxlbmRhcmlvfQp4IDwtIHRzKGZyZXF1ZW5jeSA9IDEyLCBzdGFydCA9IGMoMTk3OSwgMSksIGVuZCA9IGMoMTk5OCwgMTIpKQpjZSA8LSBjYWxlbmRhci5lZmZlY3RzKHgsIGxlYXAueWVhciA9IFRSVUUpCmNvbG5hbWVzKGNlKQpjZQpjbGFzcyhjZSkKcGxvdChjZSwgbWFpbiA9ICJjYWxlbmRhciBlZmZlY3RzIikKIyBFYXN0ZXIgZGF5cyBmb3IgZWFjaCB5ZWFyCmNhbGVuZGFyLmVmZmVjdHMoeCwgZWFzdGVyLmRhdGUgPSBUUlVFKSRlYXN0ZXIKCiMjIwp0YyA8LSByZXAoMCwgbGVuZ3RoKHgpKQp0Y1sxMTBdIDwtIDEKbHMgPC0gc3RhdHM6OmZpbHRlcih0YywgZmlsdGVyID0gMSwgbWV0aG9kID0gInJlY3Vyc2l2ZSIpCnBsb3QobHMsIG1haW4gPSAiRnVuY2nDs24gUGFzbyAtIFRDIGRlbHRhID0gMSIsIHR5cGUgPSAicyIpCgojIyNVbmllbmRvIHRvZG9zIGxvcyBlZmVjdG9zCgpjbGFzcyhjZSk8LSJtYXRyaXgiCmxleT1hcy5tYXRyaXgobHMpCmNvbG5hbWVzKGxleSk8LSJsZXkiCmVmZWN0b3M8LWNiaW5kKGNlLGxleSkKZWZlY3RvcwpgYGAKClZhbW9zIGFqdXN0YXIgdW4gbW9kZWxvIGJhc2FkbyBlbiBlbCBsb2dhcml0bW8gZGVsIG7Dum1lcm8gZGUgYWNjaWRlbnRlcy4gVW4gbW9kZWxvIGluY2lhbCBwcm9wdWVzdG8gc2luIGxhcyByZWdyZXNvcmFzIGVzOgokJFNBUklNQSgoMiwxLDApXHRpbWVzKDEsMSwxKSkkJAoKYGBge3IgYWp1c3RlIGRlbCBtb2RlbG8gMX0KbGlicmFyeShmb3JlY2FzdCkKbGlicmFyeShsbXRlc3QpCmFjY2lkZW50ZXNfdHM9dHMoQWNjaWRlbnRlcyRBY2NpZGVudGVzLHN0YXJ0PWMoMTk3OSwxKSxmcmVxdWVuY3k9MTIpCm1vZGVsb19hY2NpZGVudGVzID0gQXJpbWEoYWNjaWRlbnRlc190cywgYygyLCAxLCAwKSxzZWFzb25hbCA9IGxpc3Qob3JkZXIgPSBjKDEsIDEsIDEpLCBwZXJpb2QgPSAxMiksbGFtYmRhID0gMCkKCmNvZWZ0ZXN0KG1vZGVsb19hY2NpZGVudGVzKQojIyNJbmNvcnBvcmFuZG8gcmVncmVzb3Jhcwptb2RlbG9fYWNjaWRlbnRlc194cmVnID0gQXJpbWEoYWNjaWRlbnRlc190cywgYygyLCAxLCAwKSxzZWFzb25hbCA9IGxpc3Qob3JkZXIgPSBjKDEsIDEsIDEpLCBwZXJpb2QgPSAxMiksbGFtYmRhID0gMCx4cmVnID0gZWZlY3RvcykKCmNvZWZ0ZXN0KG1vZGVsb19hY2NpZGVudGVzX3hyZWcpCnJlZ3Jlc29yYXNfZnV0dXJhcz1tYXRyaXgoYygzLDAsMCwxKSwxLDQpCmg9MTIKZm9yZWNhc3Q6OmZvcmVjYXN0KG1vZGVsb19hY2NpZGVudGVzX3hyZWcsaD0xLHhyZWc9cmVncmVzb3Jhc19mdXR1cmFzKQpgYGAKCmBgYHtyIGFqdXN0ZSBkZWwgbW9kZWxvMn0KYWp1c3RlX2ZpbmFsPC1hdXNfY2FmZSU+JW1vZGVsKAogIGBGb3VyaWVySz0xYD1BUklNQShsb2coVHVybm92ZXIpfmZvdXJpZXIoSz0xKStwZHEoMSwxLDApK1BEUSgwLDAsMCksKSwKICBgRm91cmllcks9MmA9QVJJTUEobG9nKFR1cm5vdmVyKX5mb3VyaWVyKEs9MikrcGRxKDEsMSwwKStQRFEoMCwwLDApKSwKICBgRm91cmllcks9M2A9QVJJTUEobG9nKFR1cm5vdmVyKX5mb3VyaWVyKEs9MykrcGRxKDEsMSwwKStQRFEoMCwwLDApKSwKICBgRHVtbXlgPUFSSU1BKGxvZyhUdXJub3Zlcil+c2Vhc29uKCkrcGRxKDEsMSwwKStQRFEoMCwwLDApKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKYGBgCgoKCgo=